package com.letoken.platform.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.letoken.platform.app.service.LetokenUserService;
import com.letoken.platform.app.util.ImHttpUtil;
import com.letoken.platform.pub.annotation.auth.AdminPerm;
import com.letoken.platform.pub.constant.ConstantsValue;
import com.letoken.platform.pub.constant.LetokenUserConstant;
import com.letoken.platform.pub.enums.ApiResponseEnum;
import com.letoken.platform.pub.enums.LetokenApiResponseEnum;
import com.letoken.platform.pub.enums.LetokenEcoLevelEnum;
import com.letoken.platform.pub.enums.LetokenTokenTypeEnum;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.pub.util.BigDecimalUtil;
import com.letoken.platform.pub.util.UUIDUtil;
import com.letoken.platform.repo.admin.dao.AdminRechargeConfigMapper;
import com.letoken.platform.repo.admin.po.AdminRechargeConfig;
import com.letoken.platform.repo.app.dao.AppEcoLevelMapper;
import com.letoken.platform.repo.app.dao.AppUserLampMapper;
import com.letoken.platform.repo.app.dto.UpdateImUserInfoDto;
import com.letoken.platform.repo.app.manager.AdminRechargeConfigManager;
//import com.letoken.platform.repo.app.manager.AppUserAddressManager;
import com.letoken.platform.repo.app.manager.AppUserManager;
import com.letoken.platform.repo.app.po.*;
import com.letoken.platform.repo.app.redis.AppLoginTokenRedis;
import com.letoken.platform.repo.app.req.user.*;
import com.letoken.platform.repo.app.res.user.QueryAddressTokenRes;
import com.letoken.platform.repo.app.res.user.QueryAmbassadorEquityRes;
import com.letoken.platform.repo.app.res.user.QueryAppUserRes;
import com.letoken.platform.repo.awss3.service.AWSS3Service;
import com.letoken.platform.repo.mall.dao.AdminMallAmbassadorMapper;
import com.letoken.platform.repo.mall.dao.AppMallAmbassadorMapper;
import com.letoken.platform.repo.mall.dao.AppMallInfoMapper;
import com.letoken.platform.repo.mall.dao.AppMallPromotionMapper;
import com.letoken.platform.repo.mall.po.AdminMallAmbassador;
import com.letoken.platform.repo.mall.po.AppMallAmbassador;
import com.letoken.platform.repo.mall.po.AppMallInfo;
import com.letoken.platform.repo.mall.po.AppMallPromotion;
import com.letoken.platform.repo.utlis.LocalBlockUtils;
import com.letoken.platform.repo.utlis.WebUtils;
import com.mysql.cj.util.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author letokenlabs
 * @date 2022/11/12$
 */
@Service
@Log4j2
public class LetokenUserServiceImpl implements LetokenUserService {

//    @Resource
//    private AppUserAddressManager addressManager;
    @Autowired
    private AppUserManager appUserManager;
    @Autowired
    private AppEcoLevelMapper ecoLevelMapper;
    @Autowired
    private AdminRechargeConfigMapper rechargeMapper;
    @Autowired
    private AdminRechargeConfigManager rechargeManager;
    @Autowired
    private AWSS3Service aWSS3Service;
    @Autowired
    AppMallPromotionMapper appMallPromotionMapper;
    @Autowired
    AppMallAmbassadorMapper appMallAmbassadorMapper;
    @Autowired
    AdminMallAmbassadorMapper adminMallAmbassadorMapper;
    @Resource
    private AppMallInfoMapper appMallInfoMapper;

    @Resource
    AppUserLampMapper appUserLampMapper;

    private static final List<String> IMAGE_TYPE_LIST = new ArrayList<>();
    public LetokenUserServiceImpl(){
        IMAGE_TYPE_LIST.add("jpg");
        IMAGE_TYPE_LIST.add("jpeg");
        IMAGE_TYPE_LIST.add("png");
    }



    /**
     * 修改用户名
     *
     * @param req
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserName(UpdateUserNameReq req) {
        Integer userId = WebUtils.getUserId();
        String token = WebUtils.getToken();
        String userName = req.getUserName();
        if (userName.contains(" ")) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_016);
        }
        AppUser appUser = appUserManager.queryById(userId);
        appUser.setUserName(userName);
        appUser.setUpdateTime(LocalDateTime.now());
        Integer flag = appUserManager.updateById(appUser);
        if (flag > 0) {
            try {
                //修改im用户
                UpdateImUserInfoDto dto = new UpdateImUserInfoDto();
                dto.setUserId(LetokenUserConstant.USER_ID_PREFIX + appUser.getId());
                dto.setDisplayName(userName);
                ImHttpUtil.updateUserInfo(token, appUser.getId(), dto);
            } catch (Exception e) {
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_WALLET_TX_001);
            }
            //更新缓存
            AppLoginTokenRedis.me().put(token, appUser);
        }
    }

    /**
     * 用户修改头像
     *
     * @param file
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String updateUserHeadImage(MultipartFile file) {
        if (file.isEmpty()) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_012);
        }
        boolean flag = false;
        //校验文件类型
        for (String imageType : IMAGE_TYPE_LIST) {
            if (StringUtils.endsWithIgnoreCase(Objects.requireNonNull(file.getOriginalFilename()), imageType)) {
                flag = true;
                break;
            }
        }
        if (flag) {
            String key = "leTokenApp/avatar/" + UUIDUtil.getUUID(16);
            String url = aWSS3Service.uploadFile(file, key);
            AppUser appUser = appUserManager.queryMe();
            appUser.setHeadPortrait(url);
            appUser.setUpdateTime(LocalDateTime.now());
            appUser.updateById();
            try {
                //修改im用户
                UpdateImUserInfoDto dto = new UpdateImUserInfoDto();
                dto.setUserId(LetokenUserConstant.USER_ID_PREFIX + appUser.getId());
                dto.setPortrait(url);
                ImHttpUtil.updateUserInfo(WebUtils.getToken(), appUser.getId(), dto);
            } catch (Exception e) {
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_WALLET_TX_001);
            }
            //放进缓存
            AppLoginTokenRedis.me().put(WebUtils.getToken(), appUser);
            return url;
        } else {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_013);
        }
    }


    /**
     * 查询用户信息
     *
     * @return
     */
    @Override
    public QueryAppUserRes queryAppUser() {
        AppUser appUser = appUserManager.queryMe();
//        rechargeMapper.
        AppUserTeam appUserTeam = appUserManager.queryLevelByUserId(appUser.getId());
        LambdaQueryWrapper<AppEcoLevel> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.orderByAsc(AppEcoLevel::getLevel);
        //查询所有等级
        List<AppEcoLevel> appEcoLevelList = ecoLevelMapper.selectList(queryWrapper);
        //下一级所需的生态建值
        Integer ecoValue = null;
        //当前等级对象
        AppEcoLevel ecoLevelValue = null;
        Integer accelerateRound = 0;
        for (AppEcoLevel ecoLevel : appEcoLevelList) {
            if (ecoLevel.getLevel().equals(appUserTeam.getEcoLevel() + 1)) {
                ecoValue = ecoLevel.getEcoValue();
            }
            if (ecoLevel.getLevel().equals(appUserTeam.getEcoLevel())) {
                accelerateRound = ecoLevel.getAccelerateRound();
                ecoLevelValue = ecoLevel;
            }
        }
        if (ecoLevelValue == null) {
            ecoLevelValue = new AppEcoLevel();
            ecoLevelValue.setLevel(LetokenEcoLevelEnum.LEVEL0.getLevel());
            ecoLevelValue.setEcoValue(LetokenEcoLevelEnum.LEVEL0.getEcoValue());
            ecoLevelValue.setAccelerateRound(LetokenEcoLevelEnum.LEVEL0.getAccelerateRound());
            ecoLevelValue.setName(LetokenEcoLevelEnum.LEVEL0.getName());
        }
        BigDecimal subtract = BigDecimal.ZERO;
        if (appUserTeam.getEcoLevel() < 3) {
            subtract = BigDecimalUtil.subtract(new BigDecimal(ecoValue), appUserTeam.getEcoValue());
            //subtract = new BigDecimal(ecoValue);
        }

        QueryAppUserRes res = new QueryAppUserRes();
        res.setUserName(appUser.getUserName());
        res.setHeadImage(appUser.getHeadPortrait());
        res.setUserId(LetokenUserConstant.USER_ID_PREFIX + appUser.getId());
        //生态建设值
//        res.setEcoLevel(appUserTeam.getEcoLevel());
        res.setEcoValue(appUserTeam.getEcoValue().setScale(5, RoundingMode.DOWN));
        res.setAccelerateRound(accelerateRound);
        res.setInvitationCode(appUser.getInvitationCode());
        res.setToEcoValue(subtract.setScale(5, RoundingMode.DOWN));
        res.setUserAddress(appUser.getWalletAddress());
        res.setMaxLevel(appEcoLevelList.get(appEcoLevelList.size() - 1).getLevel());
        if (ecoValue == null) {
            res.setLevelProgressBar(new BigDecimal(1));
        } else {
            //升级当前等级生态建设值要求
            BigDecimal levelValue = new BigDecimal(ecoLevelValue.getEcoValue());
            BigDecimal sub1 = res.getEcoValue().subtract(levelValue);
            BigDecimal sub2 = new BigDecimal(ecoValue).subtract(levelValue);
            BigDecimal levelProgressBar = BigDecimalUtil.divide(sub1, sub2);
//            BigDecimal levelProgressBar = BigDecimalUtil.divide(res.getEcoValue(), new BigDecimal(ecoValue));
            res.setLevelProgressBar(levelProgressBar);
        }
        Boolean flag = rechargeManager.queryRechargeLocked(LetokenTokenTypeEnum.USDT.getId());
        String address = "";
        if (!flag){

            LocalBlockUtils.AddressPo  po1 = LocalBlockUtils.obtainAddress(LocalBlockUtils.ObtainAddressDto.builder()
                    .userId(appUser.getId())
                    .coinId(LetokenTokenTypeEnum.USDT.getId())
                    .build());
            LocalBlockUtils.AddressPo  po2 = LocalBlockUtils.obtainAddress(LocalBlockUtils.ObtainAddressDto.builder()
                    .userId(appUser.getId())
                    .coinId(LetokenTokenTypeEnum.LET.getId())
                    .build());

            address =  po1.getAddr();// addressManager.queryWalletByUserId(appUser.getId());
            log.info("查询用户信息结果：{} {}",JSON.toJSONString(po1),  JSON.toJSONString(po2));
        }
        res.setAddress(address);


        LambdaQueryWrapper<AppMallPromotion> lqwamp = new LambdaQueryWrapper<>();
        lqwamp.eq(AppMallPromotion::getUserId,appUser.getId()).eq(AppMallPromotion::getState, ConstantsValue.I_0)
                        .select(AppMallPromotion::getLevel);
        AppMallPromotion appMallPromotion =  appMallPromotionMapper.selectOne(lqwamp);
        if (ObjectUtils.isNotEmpty(appMallPromotion)){
            res.setPromotionLevel(appMallPromotion.getLevel());
        }
        LambdaQueryWrapper<AppMallAmbassador> lqwama = new LambdaQueryWrapper<>();
        lqwama.eq(AppMallAmbassador::getUserId,appUser.getId()).eq(AppMallAmbassador::getState, ConstantsValue.I_0)
                .select(AppMallAmbassador::getLevel);
        AppMallAmbassador appMallAmbassador =  appMallAmbassadorMapper.selectOne(lqwama);
        if (ObjectUtils.isNotEmpty(appMallAmbassador)){
            res.setAmbassadorLevel(appMallAmbassador.getLevel());
        }


       AppUserLamp appUserLamp = appUserLampMapper.selectById(appUser.getId());
        if(org.springframework.util.ObjectUtils.isEmpty(appUserLamp)){
            res.setLampLevel(0);
        }else{
            res.setLampLevel(appUserLamp.getLevel());
        }
        res.setCommunityLevel(appUserTeam.getLevel());
        AppMallInfo appMallInfo = appMallInfoMapper.selectMallByUserId(appUser.getId());
        if(null != appMallInfo){
            res.setShopId(appMallInfo.getId());
        }
        return res;
    }

    /**
     * 根据地址查询资产列表
     *
     * @param req
     * @return
     */
    @Override
    public List<QueryAddressTokenRes> queryAddressToken(QueryAddressTokenReq req) {


        return null;
    }


    /**
     * 查询用户的邀请码
     *
     * @return
     */
    @Override
    public String queryAppUserInviteCode() {
        AppUser appUser = AppLoginTokenRedis.me().getClassObject(WebUtils.getUserToken());
        return appUser.getInvitationCode();
    }






    @Override
    public QueryAmbassadorEquityRes ambassadorEquity() {
        QueryAmbassadorEquityRes res = new QueryAmbassadorEquityRes();
        Integer userId = WebUtils.getUserId();
        if (null == appMallAmbassadorMapper.ambassadorExists(userId)){
            return res;
        }
        QueryAmbassadorEquityRes resNew = appMallAmbassadorMapper.queryAmbassadorInfo(userId);
        if (ObjectUtils.isEmpty(resNew)){
            return res;
        }
        res = resNew;
        LambdaQueryWrapper<AdminMallAmbassador> lqwAma = new LambdaQueryWrapper<>();
        lqwAma.eq(AdminMallAmbassador::getState,ConstantsValue.I_0)
                .select(AdminMallAmbassador::getBonus,AdminMallAmbassador::getEco,AdminMallAmbassador::getLevel,AdminMallAmbassador::getLevelName)
                .orderByAsc(AdminMallAmbassador::getLevel);
        List<AdminMallAmbassador> equityList = adminMallAmbassadorMapper.selectList(lqwAma);
        if (CollectionUtils.isEmpty(equityList)){
            return res;
        }
        res.setEquityList(equityList.stream().map(x->{
            QueryAmbassadorEquityRes.AdminMallAmbassadorVo vo = new QueryAmbassadorEquityRes.AdminMallAmbassadorVo();
            BeanUtils.copyProperties(x,vo);
            return vo;
        }).collect(Collectors.toList()));

        Boolean hit = false;
        for (AdminMallAmbassador a : equityList){
            if (hit){
                res.setNextLevelEco(a.getEco());
                res.setNextLevelName(a.getLevelName());
                break;
            }
            if (a.getLevel().equals(res.getLevel())){
                hit = true;
            }
        }

        return res;
    }
}
